﻿using ComputedTable.Version10;
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Linq;

namespace MortgageCalculator.Demo
{
    public class MortgageCalculatorOutput
    {
        public decimal MonthlyLoanPayments { get; set; }
        public decimal TotalLoanPayments { get; set; }
        public decimal TotalInterestPaid { get; set; }
        public decimal TotalMonthlyPayments { get; set; }
        public List<AmortizationRecord> AmortizationTable { get; set; }
        public List<string> Warnings { get; set; }
        
        public bool Succeed 
        {
            get { return string.IsNullOrEmpty(this.Error); }
        }

        public string Error { get; internal set; }

        public override string ToString()
        {
            if (!this.Succeed)
            {
                return this.Error;
            }
            
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("Monthly Loan Payments: {0}\n", this.MonthlyLoanPayments.ToStringCurrency());
            sb.AppendFormat("Total Monthly Payments: {0}\n", this.TotalMonthlyPayments.ToStringCurrency());
            sb.AppendFormat("Total Loan Payments: {0}\n", this.TotalLoanPayments.ToStringCurrency());
            sb.AppendFormat("Total Interest Paid: {0}\n", this.TotalInterestPaid.ToStringCurrency());

            sb.AppendLine();
            if (this.Warnings == null)
            {
                sb.AppendLine("Warnings: None.");
            }
            else
            {
                sb.AppendLine("Warnings: ");
                sb.AppendLine(string.Join("\n", this.Warnings));
            }

            sb.AppendLine();
            sb.AppendLine("AmortizationTable:");
            if (this.AmortizationTable.Count > 0)
            {
                foreach (var item in this.AmortizationTable)
                {
                    sb.AppendLine(item.ToString());
                }
            }
            else
            {
                sb.AppendLine("Empty");
            }

            return sb.ToString();
        }

        public void SetAmortizationTable(Table<int, string, MortgageCalculatorOperationContext> table)
        {
            this.AmortizationTable = new List<AmortizationRecord>();
            foreach(var row in table.Rows)
            {
                var record = new AmortizationRecord();
                record.ClosingBalance = row.GetCellByColumn(AmortizationTableColumns.ClosingBalance).GetValueAsDecimal();
                record.Interest = row.GetCellByColumn(AmortizationTableColumns.Interest).GetValueAsDecimal();
                record.OpeningBalance = row.GetCellByColumn(AmortizationTableColumns.OpeningBalance).GetValueAsDecimal();
                record.PaymentDate = row.GetCellByColumn(AmortizationTableColumns.PaymentDate).GetValueAsDateTime();
                record.PaymentNumber = row.GetCellByColumn(AmortizationTableColumns.PaymentNumber).GetValueAsInt();
                record.Principal = row.GetCellByColumn(AmortizationTableColumns.Principal).GetValueAsDecimal();
                record.PropertyTax = row.GetCellByColumn(AmortizationTableColumns.PropertyTax).GetValueAsDecimal();
                record.RemainingPayments = row.GetCellByColumn(AmortizationTableColumns.RemainingPayments).GetValueAsInt();
                record.TotalPayments = row.GetCellByColumn(AmortizationTableColumns.TotalPayments).GetValueAsDecimal();

                this.AmortizationTable.Add(record);
            }
        }

        public XElement AmortizationTableAsXml()
        {
            XElement xml = new XElement("table");
            var properties = typeof(AmortizationRecord).GetProperties();

            foreach(var item in this.AmortizationTable)
            {
                var row = new XElement("row");
                foreach (var property in properties)
                {
                    var attribute = new XAttribute(property.Name, property.GetValue(item).ToString());
                    row.Add(attribute);
                }

                xml.Add(row);
            }

            return xml;
        }

        public class AmortizationRecord
        {
            public int PaymentNumber { get; set; }
            public int RemainingPayments { get; set; }
            public decimal PropertyTax { get; set; }
            public decimal Interest { get; set; }
            public decimal Principal { get; set; }
            public decimal OpeningBalance { get; set; }
            public decimal ClosingBalance { get; set; }
            public DateTime PaymentDate { get; set; }
            public decimal TotalPayments { get; set; }

            public override string ToString()
            {
                return string.Format("PaymentNumber: {0}, RemainingPayments: {1}, PropertyTax: {2}, Interest: {3}, Principal: {4}, OpeningBalance: {5}, ClosingBalance: {6}, PaymentDate: {7}, TotalPayments: {8}",
                    this.PaymentNumber,
                    this.RemainingPayments,
                    this.PropertyTax.ToStringCurrency(),
                    this.Interest.ToStringCurrency(),
                    this.Principal.ToStringCurrency(),
                    this.OpeningBalance.ToStringCurrency(),
                    this.ClosingBalance.ToStringCurrency(),
                    this.PaymentDate.ToShortDateString(),
                    this.TotalPayments.ToStringCurrency());
            }
        }
    }

    public class InterestRateCalculationOutput
    {
        public decimal? InterestRate { get; set; }
        public string Message { get; set; }

        public override string ToString()
        {
            if (this.InterestRate.HasValue)
            {
                return string.Format("Interest Rate: {0}", this.InterestRate.Value.ToStringPercentage());
            }
            else
            {
                return this.Message;

            }
        }
    }
}